#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <unordered_map>

const static std::string base_sep = "\r\n";
const static std::string line_sep = ": ";
const static std::string prefixpath = "wwwroot"; // Web 根目录
const static std::string homepage = "index.html";
const static std::string httpversion = "HTTP/1.0";
const static std::string spacesep = " ";
const static std::string suffixsep = ".";

class Request
{
private:
    std::string GetLine(std::string &reqstr)
    {
        auto pos = reqstr.find(base_sep);
        if (pos == std::string::npos) // 没有正文
            return "";
        std::string line = reqstr.substr(0, pos);
        reqstr.erase(0, line.size() + base_sep.size());
        return line.empty() ? base_sep : line;
    }

    void ParseLine()
    {
        std::stringstream ss(_req_line);
        ss >> _method >> _url >> _version;

        _path += _url;

        // 当用户访问 / 的时候 显示默认的 index页面
        if (_path[_path.size() - 1] == '/')
            _path += homepage;

        // 确定请求资源后缀
        auto pos = _path.rfind(suffixsep);
        if (pos == std::string::npos)
        {
            _suffix = ".default";
        }
        else
        {
            _suffix = _path.substr(pos);
        }
    }

    void ParseHeaser()
    {
        for (auto &header : _req_headers)
        {
            auto pos = header.find(line_sep);
            if (pos == std::string::npos)
                continue;
            std::string k = header.substr(0, pos);
            std::string v = header.substr(pos + line_sep.size());
            if (k.empty() || v.empty())
                continue;
            _headers_kv[k] = v;
        }
    }

public:
    Request()
        : _blank_line(base_sep), _path(prefixpath)
    {
    }

    ~Request()
    {
    }

    void Deserialize(std::string &reqstr)
    {
        // 基本反序列化
        _req_line = GetLine(reqstr);
        std::string header;
        do
        {
            header = GetLine(reqstr);
            if (header.empty() || header == base_sep)
                break;
            _req_headers.emplace_back(header);
        } while (true);

        if (!reqstr.empty())
        {
            _req_body_text = reqstr;
        }

        // 进一步反序列化
        ParseLine();
        ParseHeaser();
    }

    std::string Url()
    {
        LOG(DEBUG, "Client want url: %s\n", _url.c_str());
        return _url;
    }

    std::string Path()
    {
        LOG(DEBUG, "Client want path: %s\n", _path.c_str());
        return _path;
    }

    std::string Suffix()
    {
        return _suffix;
    }

    void Print()
    {
        std::cout << "-------------------------------------" << std::endl;
        std::cout << "###" << _req_line << std::endl;
        for (auto &header : _req_headers)
        {
            std::cout << "@@@" << header << std::endl;
        }
        std::cout << "***" << _blank_line;
        std::cout << ">>>" << _req_body_text << std::endl;

        std::cout << "Method: " << _method << std::endl;
        std::cout << "Url: " << _url << std::endl;
        std::cout << "Version: " << _version << std::endl;

        for (auto &h : _headers_kv)
        {
            std::cout << ")))" << h.first << "->" << h.second << std::endl;
        }
    }

private:
    // 基本的属性
    std::string _req_line;                 // 请求行
    std::vector<std::string> _req_headers; // 请求报头
    std::string _blank_line;               // 空白行
    std::string _req_body_text;            // 正文数据

    // 详细属性
    std::string _method;
    std::string _url;
    std::string _path;
    std::string _suffix; // 请求资源的后缀
    std::string _version;
    std::unordered_map<std::string, std::string> _headers_kv;
};

class Response
{
public:
    Response() : _blank_line(base_sep), _version(httpversion)
    {
    }

    ~Response()
    {
    }

    void AddCode(int code, const std::string &desc)
    {
        _status_code = code;
        _desc = desc;
    }

    void AddHeader(const std::string &k, const std::string &v)
    {
        _headers_kv[k] = v;
    }

    void AddBodyText(const std::string &bodytext)
    {
        _resp_body_text = bodytext;
    }

    std::string Serialize()
    {
        // 1、构建状态行
        _status_line = _version + spacesep + std::to_string(_status_code) + spacesep + _desc + base_sep;
        // 2、构建响应报头
        for (auto &header : _headers_kv)
        {
            std::string header_line = header.first + line_sep + header.second + base_sep;
            _resp_headers.emplace_back(header_line);
        }
        // 3、空行和正文

        // 4、正式的序列化
        std::string resopsestr = _status_line;
        for (auto &line : _resp_headers)
        {
            resopsestr += line;
        }

        resopsestr += _blank_line;
        resopsestr += _resp_body_text;

        return resopsestr;
    }

private:
    // 基本的属性
    std::string _status_line;               // 请求行
    std::vector<std::string> _resp_headers; // 请求报头
    std::string _blank_line;                // 空白行
    std::string _resp_body_text;            // 正文数据

    // 详细属性
    std::string _version;
    int _status_code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _headers_kv;
};

class HttpServer
{
private:
    std::string GetFileContent(std::string path)
    {
        std::ifstream in(path, std::ios::binary); // 二进制的形式
        if (!in.is_open())
            return "";

        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        std::string content;
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);

        in.close();

        return content;
    }

public:
    HttpServer()
    {
        _mime_type.insert(std::make_pair(".html", "text/html"));
        _mime_type.insert(std::make_pair(".jpg", "image/jpeg"));
        _mime_type.insert(std::make_pair(".png", "image/png"));
        _mime_type.insert(std::make_pair(".default", "text/html"));

        _code_to_desc.insert(std::make_pair(100, "Continue"));
        _code_to_desc.insert(std::make_pair(200, "OK"));
        _code_to_desc.insert(std::make_pair(201, "Created"));
        _code_to_desc.insert(std::make_pair(301, "Moved Permanently"));
        _code_to_desc.insert(std::make_pair(302, "Found"));
        _code_to_desc.insert(std::make_pair(404, "Not Found"));
    }
    ~HttpServer() {}

    std::string HandlerHttpServer(std::string &requeststr)
    {
#ifdef TEST
        std::cout << "---------------------------" << std::endl;
        std::cout << requeststr;

        std::string responsestr = "HTTP/1.1 200 OK\r\n";
        responsestr += "Content-Type: text/html\r\n";
        responsestr += "\r\n";
        responsestr += "<html><h1>hello world</h1></html>";
        return responsestr;
#else
        Request req;
        req.Deserialize(requeststr);
        // req.Print();
        // req.Url();
        // req.Path();
        Response resp;

        std::string content = GetFileContent(req.Path());
        if (content.empty())
        {
            content = GetFileContent("wwwroot/404.html");
            resp.AddCode(404, _code_to_desc[404]);
            resp.AddHeader("Content-Length", std::to_string(content.size()));
            resp.AddHeader("Content-Type", _mime_type[".html"]);
            resp.AddBodyText(content);
        }
        else
        {
            resp.AddCode(200, "OK");
            resp.AddHeader("Content-Length", std::to_string(content.size()));
            resp.AddHeader("Content-Type", _mime_type[req.Suffix()]);
            resp.AddBodyText(content);
        }

        return resp.Serialize();
#endif
        return "";
    }

private:
    std::unordered_map<std::string, std::string> _mime_type;
    std::unordered_map<int, std::string> _code_to_desc;
};